const Package = require('../models/Package');
const DownloadStat = require('../models/DownloadStat');
const Tag = require('../models/Tag');
const Discussion = require('../models/Discussion');
const { Op } = require('sequelize');

class StatsService {
  // 获取统计概览
  async getOverviewStats({ timeRange, startDate, endDate }) {
    try {
      const dateFilter = this.getDateFilter(timeRange, startDate, endDate);
      
      // 获取总数据
      const totalPackages = await Package.count();
      const totalTags = await Tag.count();
      const totalDiscussions = await Discussion.count();
      
      // 获取总下载量
      const downloadStats = await DownloadStat.sum('downloads');
      const totalDownloads = downloadStats || 0;
      
      // 计算变化率（简化实现，实际应该对比上一期数据）
      const downloadChange = Math.floor(Math.random() * 20) - 5; // 模拟数据
      const packageChange = Math.floor(Math.random() * 15) - 3;
      const tagChange = Math.floor(Math.random() * 10) - 2;
      const discussionChange = Math.floor(Math.random() * 25) - 8;
      
      return {
        totalDownloads,
        totalPackages,
        totalTags,
        totalDiscussions,
        downloadChange,
        packageChange,
        tagChange,
        discussionChange
      };
    } catch (error) {
      console.error('获取统计概览失败:', error);
      throw new Error('获取统计概览失败');
    }
  }
  
  // 获取下载趋势
  async getDownloadTrend({ timeRange, startDate, endDate }) {
    try {
      const dateFilter = this.getDateFilter(timeRange, startDate, endDate);
      
      const stats = await DownloadStat.findAll({
        where: dateFilter,
        attributes: [
          'date',
          [DownloadStat.sequelize.fn('SUM', DownloadStat.sequelize.col('downloads')), 'totalDownloads']
        ],
        group: ['date'],
        order: [['date', 'ASC']],
        raw: true
      });
      
      const dates = stats.map(stat => stat.date);
      const downloads = stats.map(stat => parseInt(stat.totalDownloads) || 0);
      
      return { dates, downloads };
    } catch (error) {
      console.error('获取下载趋势失败:', error);
      throw new Error('获取下载趋势失败');
    }
  }
  
  // 获取热门包
  async getTopPackages({ timeRange, startDate, endDate, limit = 10 }) {
    try {
      const packages = await Package.findAll({
        order: [['downloads', 'DESC']],
        limit: parseInt(limit),
        attributes: ['name', 'downloads']
      });
      
      return packages;
    } catch (error) {
      console.error('获取热门包失败:', error);
      throw new Error('获取热门包失败');
    }
  }
  
  // 获取标签分布
  async getTagDistribution() {
    try {
      const tags = await Tag.findAll({
        order: [['count', 'DESC']],
        limit: 10,
        attributes: ['name', 'count']
      });
      
      return tags.map(tag => ({
        name: tag.name,
        value: tag.count
      }));
    } catch (error) {
      console.error('获取标签分布失败:', error);
      throw new Error('获取标签分布失败');
    }
  }
  
  // 获取讨论活跃度
  async getDiscussionActivity({ timeRange, startDate, endDate }) {
    try {
      const dateFilter = this.getDateFilter(timeRange, startDate, endDate);
      
      // 获取最近7天的数据
      const endDate7 = new Date();
      const startDate7 = new Date();
      startDate7.setDate(startDate7.getDate() - 6);
      
      const discussions = await Discussion.findAll({
        where: {
          created_at: {
            [Op.between]: [startDate7, endDate7]
          }
        },
        attributes: [
          [Discussion.sequelize.fn('DATE', Discussion.sequelize.col('created_at')), 'date'],
          [Discussion.sequelize.fn('COUNT', Discussion.sequelize.col('id')), 'count']
        ],
        group: [Discussion.sequelize.fn('DATE', Discussion.sequelize.col('created_at'))],
        order: [[Discussion.sequelize.fn('DATE', Discussion.sequelize.col('created_at')), 'ASC']],
        raw: true
      });
      
      // 生成完整的7天数据
      const dates = [];
      const discussionCounts = [];
      const commentCounts = [];
      
      for (let i = 6; i >= 0; i--) {
        const date = new Date();
        date.setDate(date.getDate() - i);
        const dateStr = date.toISOString().split('T')[0];
        dates.push(date.toLocaleDateString('zh-CN', { month: '2-digit', day: '2-digit' }));
        
        const dayData = discussions.find(d => d.date === dateStr);
        const count = dayData ? parseInt(dayData.count) : 0;
        discussionCounts.push(count);
        commentCounts.push(Math.floor(count * 2.5)); // 模拟评论数
      }
      
      return {
        dates,
        discussions: discussionCounts,
        comments: commentCounts
      };
    } catch (error) {
      console.error('获取讨论活跃度失败:', error);
      throw new Error('获取讨论活跃度失败');
    }
  }
  
  // 获取详细下载统计
  async getDownloadDetails({ timeRange, startDate, endDate }) {
    try {
      const dateFilter = this.getDateFilter(timeRange, startDate, endDate);
      
      const stats = await DownloadStat.findAll({
        where: dateFilter,
        attributes: [
          'date',
          [DownloadStat.sequelize.fn('SUM', DownloadStat.sequelize.col('downloads')), 'totalDownloads']
        ],
        group: ['date'],
        order: [['date', 'DESC']],
        limit: 10,
        raw: true
      });
      
      const totalPackages = await Package.count();
      
      return stats.map((stat, index) => {
        const downloads = parseInt(stat.totalDownloads) || 0;
        return {
          date: new Date(stat.date).toLocaleDateString('zh-CN'),
          downloads,
          uniqueVisitors: Math.floor(downloads * 0.7),
          avgDownloadsPerPackage: Math.floor(downloads / totalPackages),
          trend: Math.floor(Math.random() * 30) - 10 // 模拟趋势
        };
      });
    } catch (error) {
      console.error('获取详细下载统计失败:', error);
      throw new Error('获取详细下载统计失败');
    }
  }
  
  // 辅助方法：获取日期过滤条件
  getDateFilter(timeRange, startDate, endDate) {
    const now = new Date();
    let start, end = now;
    
    switch (timeRange) {
      case 'day':
        start = new Date();
        start.setHours(0, 0, 0, 0);
        break;
      case 'week':
        start = new Date();
        start.setDate(start.getDate() - 7);
        break;
      case 'month':
        start = new Date();
        start.setMonth(start.getMonth() - 1);
        break;
      case 'year':
        start = new Date();
        start.setFullYear(start.getFullYear() - 1);
        break;
      case 'custom':
        if (startDate && endDate) {
          start = new Date(startDate);
          end = new Date(endDate);
        } else {
          start = new Date();
          start.setMonth(start.getMonth() - 1);
        }
        break;
      default:
        start = new Date();
        start.setMonth(start.getMonth() - 1);
    }
    
    return {
      date: {
        [Op.between]: [start, end]
      }
    };
  }
}

module.exports = new StatsService();